using System;
using AntEater.ComponentModel.Validation;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Diagnostics.CodeAnalysis;

namespace AntEater.ComponentModel.BuildElements
{
    /// <summary>
    /// Provides the Target build element.
    /// </summary>
    [Serializable]
    [BuildElement("Target")]
    [ChildBuildElementType(typeof(TaskBuildElement))]
    [ChildBuildElementType(typeof(ErrorBuildElement))]
    [ChildBuildElementType(typeof(WarningBuildElement))]
    [ChildBuildElementType(typeof(MessageBuildElement))]
    [ChildBuildElementType(typeof(OnErrorBuildElement))]
    [Icon(typeof(TargetBuildElement), "AntEater.ComponentModel.Resources.Target.ico")]
    public class TargetBuildElement : ContainerBuildElementBase
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="T:TargetBuildElement"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        public TargetBuildElement(BuildFileDefinition context)
            : base(context) {

            _name = "undefined";

            _dependsOnTargets = new TargetCollection(context);
            _dependsOnTargets.CollectionChanged += new EventHandler<CollectionChangeEventArgs>(DependsOnTargetsCollectionChanged);
        }

        private string _condition;

        /// <summary>
        /// Gets or sets the condition.
        /// </summary>
        /// <value>The condition.</value>
        [BuildElementProperty("Condition", false, BuildElementPropertyType.Condition)]
        [Description("Optional attribute.\nCondition to be evaluated.")]
        [Category("MsBuild")]
        public string Condition {
            get { return _condition; }
            set {
                if (_condition != value) {
                    _condition = value;
                    OnPropertyChanged("Condition");
                }
            }
        }

        private TargetCollection _dependsOnTargets;

        /// <summary>
        /// Gets or sets the depends on targets.
        /// </summary>
        /// <value>The depends on targets.</value>
        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        [BuildElementProperty("DependsOnTargets", false, BuildElementPropertyType.ListOfTargets)]
        [Description("Optional attribute.\nThe targets that must be executed before this target can execute or top level dependency analysis can occur. Multiple targets are separated by semicolons.")]
        [Category("MsBuild")]
        [Editor(typeof(Design.TargetCollectionTypeEditor), typeof(UITypeEditor))]
        public TargetCollection DependsOnTargets {
            get { return _dependsOnTargets; }
            set { _dependsOnTargets = value; }
        }

        private string _inputs;

        /// <summary>
        /// Gets or sets the inputs.
        /// </summary>
        /// <value>The inputs.</value>
        [BuildElementProperty("Inputs", false, BuildElementPropertyType.String)]
        [Description("Optional attribute.\nThe item inputs for this target. Items inside this attribute are used as the inputs in the top level dependency analysis.")]
        [Category("MsBuild")]
        public string Inputs {
            get { return _inputs; }
            set {
                if (_inputs != value) {
                    _inputs = value;
                    OnPropertyChanged("Inputs");
                }
            }
        }

        private string _name;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        [BuildElementProperty("Name", true, BuildElementPropertyType.String)]
        [Description("Required attribute.\nThe name of the target.")]
        [Category("MsBuild")]
        public string Name {
            get { return _name; }
            set {
                if (_name != value) {
                    _name = value;
                    OnPropertyChanged("Name");
                }
            }
        }

        private string _outputs;

        /// <summary>
        /// Gets or sets the outputs.
        /// </summary>
        /// <value>The outputs.</value>
        [BuildElementProperty("Outputs", false, BuildElementPropertyType.String)]
        [Description("Optional attribute.\nThe expected outputs of this target. You can apply transforms to the input items to generate the output items.")]
        [Category("MsBuild")]
        public string Outputs {
            get { return _outputs; }
            set {
                if (_outputs != value) {
                    _outputs = value;
                    OnPropertyChanged("Outputs");
                }
            }
        }

        /// <summary>
        /// Determines whether this instance is valid.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 	<c>true</c> if this instance is valid; otherwise, <c>false</c>.
        /// </returns>
        public override bool IsValid {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Validates the specified recursive.
        /// </summary>
        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
        /// <returns></returns>
        public override ReadOnlyCollection<ValidationResult> Validate(bool recursive) {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override object Clone() {
            TargetBuildElement newElement = base.Clone() as TargetBuildElement;

            if (this._condition != null) {
                newElement._condition = this._condition.Clone() as string;
            }
            newElement._dependsOnTargets.AddRange(this._dependsOnTargets.Clone() as TargetCollection);
            if (this._inputs != null) {
                newElement._inputs = this._inputs.Clone() as string;
            }
            if (this._name != null) {
                newElement._name = this._name.Clone() as string;
            }
            if (this._outputs != null) {
                newElement._outputs = this._outputs.Clone() as string;
            }

            return newElement;
        }

        /// <summary>
        /// Dependses the on targets collection changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.CollectionChangeEventArgs"/> instance containing the event data.</param>
        private void DependsOnTargetsCollectionChanged(object sender, CollectionChangeEventArgs e) {
            OnPropertyChanged("DependsOnTargets");
        }
    }
}
